/*
 * TODO language 
 * Copyright (c) 2010 TODO Team
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef TODO_EXECUTOR_H
#define TODO_EXECUTOR_H
#include <string>
#include <map>
#include <stack>
#include "types.h"

namespace todo
{
class todo_opcode;

#define HANDLER_ARGS unsigned int* op_num, TodoData& op1, TodoData& op2, todo::todo_opcode* opcode
#define JMP_OUT(jmp) \
	*op_num = jmp; \
	return;
#define JMP_TO(jmp) \
	*op_num = jmp; \
	last_jmp = jmp+1; \
	return;

class TodoExecutor {
	TodoValue* ret_value;          // the value returned by a function
	TodoScope* global_scope;       // points to the global scope
	std::stack<TodoScope*> scopes; // stacks the scopes
	TodoValue* expr_value;         // the value returned by an expression
	TodoScope* current_scope;      // points to the current scope
	unsigned int last_jmp;
public:
	TodoExecutor() : ret_value(NULL), expr_value(NULL) { }
	~TodoExecutor() { }
	
	std::map<std::string, TodoValue*>::iterator get_var(const std::string& name)
		throw (todo::TodoException);
		
	std::map<std::string, TodoFunction*>::iterator get_func(const std::string& name)
		throw (todo::TodoException);

	void init(void);
	void run(void);
	TodoValue* get_new_expr_value(void);
	TodoValue* get_val_ptr(TodoData& op) throw (todo::TodoException);

	// Handlers	
	void print(HANDLER_ARGS) throw (todo::TodoException);
	void println(HANDLER_ARGS) throw (todo::TodoException);
	void declare_var(HANDLER_ARGS);
	void declare_func(HANDLER_ARGS);
	void mod_assign(HANDLER_ARGS) throw (todo::TodoException);
	void sub_assign(HANDLER_ARGS) throw (todo::TodoException);
	void add_assign(HANDLER_ARGS) throw (todo::TodoException);
	void mult_assign(HANDLER_ARGS) throw (todo::TodoException);
	void div_assign(HANDLER_ARGS) throw (todo::TodoException);
	void free_func(HANDLER_ARGS);
	void func_call(HANDLER_ARGS);
	void change_var(HANDLER_ARGS);
	void if_stmt(HANDLER_ARGS);
	void elsif_stmt(HANDLER_ARGS);
	void else_stmt(HANDLER_ARGS);
	void endif_stmt(HANDLER_ARGS);
	void ret(HANDLER_ARGS);
	void method_call(HANDLER_ARGS);
};

typedef void (todo::TodoExecutor::*handler_op)(HANDLER_ARGS);
} // todo

extern todo::TodoExecutor executor;

#endif // TODO_EXECUTOR_H
